package gzc.netty4.client;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.io.UnsupportedEncodingException;
import java.nio.ByteOrder;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static gzc.netty4.server.Netty4ServerHandler.UTF8;

/**
 * Created by designerpc on 2016/11/26.
 */
public class Netty4ClientHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
//        for (int i = 0; i < 10; ++i) {
//            sendOneMsg(ctx);
//            sendOneMsg2(ctx);
//            sendOneMsg3(ctx);
//            sendOneMsg4(ctx);
//            sendOneMsg5(ctx);
//        }
        sendOneMsg6(ctx);
    }

    /*例子1，例子2*/
    private void sendOneMsg(ChannelHandlerContext ctx) throws Exception {
        byte[] data = "Hello, World".getBytes(UTF8);
        int bodyLen = data.length;

        ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
        buf.order(ByteOrder.BIG_ENDIAN);

        buf.writeShort(bodyLen);
        buf.writeBytes(data);

        ctx.channel().writeAndFlush(buf);
    }

    /*例子3*/
    private void sendOneMsg2(ChannelHandlerContext ctx) throws Exception {
        byte[] data = "Hello, World".getBytes(UTF8);
        // 整个消息的长度
        int msgLen = 2 + data.length;

        ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
        buf.order(ByteOrder.BIG_ENDIAN);

        buf.writeShort(msgLen);
        buf.writeBytes(data);

        ctx.channel().writeAndFlush(buf);
    }

    /*例子4*/
    private void sendOneMsg3(ChannelHandlerContext ctx) throws Exception {
        final int header1 = 0xCAFE;
        byte[] data = "Hello, World".getBytes(UTF8);
        int bodyLen = data.length;

        ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
        buf.order(ByteOrder.BIG_ENDIAN);

        buf.writeShort(header1);
        buf.writeMedium(bodyLen);
        buf.writeBytes(data);

        ctx.channel().writeAndFlush(buf);
    }

    /*例子5*/
    private void sendOneMsg4(ChannelHandlerContext ctx) throws Exception {
        final int header1 = 0xCAFE;
        byte[] data = "Hello, World".getBytes(UTF8);
        int bodyLen = data.length;

        ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
        buf.order(ByteOrder.BIG_ENDIAN);

        buf.writeMedium(bodyLen);
        buf.writeShort(header1);
        buf.writeBytes(data);

        ctx.channel().writeAndFlush(buf);
    }

    /*例子6*/
    private void sendOneMsg5(ChannelHandlerContext ctx) throws Exception {
        final int header1 = 0xCA;
        final int header2 = 0xFE;
        byte[] data = "Hello, World".getBytes(UTF8);
        int bodyLen = data.length;

        ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
        buf.order(ByteOrder.BIG_ENDIAN);

        buf.writeByte(header1);
        buf.writeShort(bodyLen);
        buf.writeByte(header2);
        buf.writeBytes(data);

        ctx.channel().writeAndFlush(buf);
    }

    /*例子7*/
    private void sendOneMsg6(ChannelHandlerContext ctx) throws Exception {
        for (int i = 0; i < 10; ++i) {
            // 封装成任务到线程里执行
            bizThread(ctx);
        }
    }

    private void bizThread(final ChannelHandlerContext ctx) {
        // 发送一个消息
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                // 休眠随机1到4秒
//                try {
//                    Thread.sleep(1000 * (int) (1 + Math.random() * (4 - 1 + 1)));
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }

                final int header1 = 0xCA;
                final int header2 = 0xFE;
                byte[] data = new byte[0];
                try {
                    data = "Hello, World".getBytes(UTF8);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                // 整个包的消息长度
                int msgLen = data.length + 1 + 1 + 2;

                ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
                buf.order(ByteOrder.BIG_ENDIAN);

                buf.writeByte(header1);
                buf.writeShort(msgLen);
                buf.writeByte(header2);
                buf.writeBytes(data);

                ctx.channel().writeAndFlush(buf);
//                ReferenceCountUtil.release(buf);
            }
        });
    }

    final private ExecutorService executorService =
            Executors.newFixedThreadPool(4);

}
